
namespace GameServer.ShootingGame.RenderableClasses
{
    using GameServer.ShootingGame.WeaponsClasses;
    using GameServer.Common;
    using System.Collections.Generic;
    using GameServer.Common.Utils;
    using System.Reflection;
    using GameServer.ShootingGame.Physics.CollisionReactionClasses;
    using GameServer.ShootingGame.Physics.CollisionReactionClasses.Base;
    using System;

    public class PlayerObject : MobileObject
    {
        public const double MAXSPEED = 0.3;
        //As a fraction of the max speed.
        public const double ACCELERATION = 0.008;
        //As a fraction of the max speed.
        public const double DECELERATION = ACCELERATION / 3.0;

        public string userName;
        public KeyStates keyStates;
        private Weapon weapon;
        private int time_MouseDown;
        private double mouseX;
        private double mouseY;

        public PlayerObject()
        {
            maxSpeed = MAXSPEED;
            canRegisterOrdinanceImpact = true;
            keyStates = new KeyStates();
            Facing = 0;
            HitPoints = HitPointMax = 100;
            time_MouseDown = 0;
            if (collisionEffects != null)
                this.collisionEffects = collisionEffects;
            else
                this.collisionEffects = new PlayerCollisionEffects(this, Colliders.PLAYER);
            mouseX = 0;
            mouseY = 0;
            IsExpired = true;
        }

        /// <summary>
        /// Updates player position in temp x,y values.
        /// </summary>
        override public void Update()
        {
            MouseLook();
            base.Update();
            List<Ordinance> firedBullets;
            if (keyStates.mouseLeft_Down)
            {
                time_MouseDown += 1;
                if (weapon != null)
                {
                    weapon.IsTriggerDepressed = true;
                    firedBullets = Attack_Primary(mouseX, mouseY);
                    if (firedBullets != null)
                    {
                        for (int i = 0; i < firedBullets.Count; i++)
                        {
                            firedBullets[i].GamePlayManager = GamePlayManager;
                            firedBullets[i].StartUpdate();
                        }
                    }
                }
            }
            else
            {
                if (weapon != null)
                    weapon.IsTriggerDepressed = false;
                time_MouseDown = 0;
            }

        }

        override protected void UpdateThrust()
        {
            double tmp_ThrustX = ThrustX;
            double tmp_ThrustY = ThrustY;
            if (keyStates.up)
            {
                if (!keyStates.down)
                    tmp_ThrustY -= ACCELERATION;
            }
            else
                if (keyStates.down)
                {
                    tmp_ThrustY += ACCELERATION;
                }
                else
                {
                    if (ThrustY > 0)
                        tmp_ThrustY -= DECELERATION;
                    else
                        if (ThrustY < 0)
                            tmp_ThrustY += DECELERATION;
                }
            if (keyStates.left)
            {
                if (!keyStates.right)
                    tmp_ThrustX -= ACCELERATION;
            }
            else
                if (keyStates.right)
                {
                    tmp_ThrustX += ACCELERATION;
                }
                else
                {
                    if (ThrustX > 0)
                        tmp_ThrustX -= DECELERATION;
                    else
                        if (ThrustX < 0)
                            tmp_ThrustX += DECELERATION;
                }

            if (!keyStates.up && !keyStates.down)
            {
                if (Math.Abs(ThrustY) < Math.Abs(tmp_ThrustY))
                    tmp_ThrustY = 0;
            }
            if (!keyStates.left && !keyStates.right)
            {
                if (Math.Abs(ThrustX) < Math.Abs(tmp_ThrustX))
                    tmp_ThrustX = 0;
            }
            ThrustX = tmp_ThrustX;
            ThrustY = tmp_ThrustY;


            if (ThrustX > 1)
                ThrustX = 1;
            else
                if (ThrustX < -1)
                    ThrustX = -1;
            if (ThrustY > 1)
                ThrustY = 1;
            else
                if (ThrustY < -1)
                    ThrustY = -1;
        }

        private void MouseLook()
        {
            Facing = Math2.GetAngleOfElevationDegree(xPosition, yPosition, mouseX, mouseY);
        }

        //Returns array of launched ordinance
        public List<Ordinance> Attack_Primary(double targetX, double targetY)
        {
            return weapon.Fire_Primary(targetX, targetY);
        }


        override public void AddAttachment(AttachableObject attch)
        {
            if (attch.GetType().ToString().Contains("Weapon") && attch != weapon)
                Weapon = attch as Weapon;
            base.AddAttachment(attch);
        }

        public Weapon Weapon
        {
            get
            {
                return weapon;
            }
            set
            {
                if (weapon != null)
                    RemoveAttachment(weapon);
                weapon = value;
                if (weapon != null)
                    if (!weapon.AttachedTo.Equals(this))
                        weapon.AttachedTo = this;
            }
        }


        /// <summary>
        /// Adds the object to the update list. Returns false if the object is already on the list.
        /// </summary>
        override public bool AddObject()
        {
            if (!GamePlayManager.PlayerList.Contains(this))
            {
                GamePlayManager.PlayerList.Add(this);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Removes the object from the update list. Returns false if the object was not on the update list.
        /// </summary>
        /// <returns></returns>
        override public bool RemoveObject()
        {
            if (GamePlayManager.PlayerList.Contains(this))
            {
                GamePlayManager.PlayerList.Remove(this);
                return true;
            }
            return false;
        }


        public double MouseX
        {
            get { return mouseX; }
            set { mouseX = value; }
        }
        public double MouseY
        {
            get { return mouseY; }
            set { mouseY = value; }
        }

        public override bool IsExpired
        {
            get
            {
                return base.IsExpired;
            }
            set
            {
                if (isExpired == value)
                    return;
                isExpired = value;
                if (isExpired)
                {
                    Weapon = null;
                    attachments = null;
                }
                else
                    HitPoints = HitPointMax;
                canRegisterOrdinanceImpact = !IsExpired;
                isHitDetectionEnabled = !IsExpired;
            }
        }

        /// <summary>
        /// Sets the respective gameobject properties to those of a newly spawned player. Returns false if the player is already spawned.
        /// </summary>
        /// <returns></returns>
        public bool Spawn()
        {
            if (!IsExpired)
                return false;
            IsExpired = false;
            return true;
        }
    }
}
